﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DbLogger.cs" company="Spenta Consulting">
//   (c) Copyright 2011
// </copyright>
// <summary>
//   ILogger implementation for logging to a StreetCareLogEntities context (ADO Entity Framework)
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Spenta.StreetCare.Core.Logging
{
    #region Using Directives

    using System;
    using Infrastructure.Configuration;
    using Infrastructure.Logging;
    using Models;

    using Spenta.StreetCare.Core.IoC;

    #endregion

    /// <summary>
    /// Log severity
    /// </summary>
    public enum DbLoggerSeverity
    {
        /// <summary>
        /// The information severity
        /// </summary>
        Information = 0,

        /// <summary>
        /// The warning severity
        /// </summary>
        Warning = 1,

        /// <summary>
        /// The error severity
        /// </summary>
        Error = 2,

        /// <summary>
        /// The critical severity
        /// </summary>
        Critical = 3
    }

    /// <summary>
    /// ILogger implementation for logging to a StreetCareLogEntities context (ADO Entity Framework)
    /// </summary>
    public class DbLogger : ILogger
    {
        #region Constants

        /// <summary>
        /// Critical severity
        /// </summary>
        public const string SeverityCritical = "Critical";

        /// <summary>
        /// Error severity
        /// </summary>
        public const string SeverityError = "Error";

        /// <summary>
        /// Warning severity
        /// </summary>
        public const string SeverityWarning = "Warning";

        /// <summary>
        /// Information severity
        /// </summary>
        public const string SeverityInformation = "Information";

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="DbLogger"/> class.
        /// </summary>
        /// <param name="configurationBag">The configuration bag.</param>
        public DbLogger(IConfigurationBag configurationBag)
        {
            DbLoggerSeverity minSeverity;
            this.MinimumSeverity = Enum.TryParse(configurationBag.GetPropertyValue("LoggerMinimumSeverity"), true, out minSeverity) ? minSeverity : DbLoggerSeverity.Warning;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the minimum severity.
        /// </summary>
        /// <value>
        /// The minimum severity.
        /// </value>
        public DbLoggerSeverity MinimumSeverity { get; set; }

        #endregion

        #region Implement Interface ILogger

        /// <summary>
        /// Writes to the log using the critical level.
        /// </summary>
        /// <param name="message">The message.</param>
        public void WriteCritical(string message)
        {
            this.AddLogEntryToContext(DbLoggerSeverity.Critical, LogCategories.StreetCare, message, null);
        }

        /// <summary>
        /// Writes to the log using the critical level.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The exception</param>
        public void WriteCritical(string message, Exception ex)
        {
            this.AddLogEntryToContext(DbLoggerSeverity.Critical, LogCategories.StreetCare, message, ex);
        }

        /// <summary>
        /// Writes to the log using the critical level.
        /// </summary>
        /// <param name="category">The category.</param>
        /// <param name="message">The message.</param>
        /// <param name="ex">The exception</param>
        public void WriteCritical(BaseCategory category, string message, Exception ex)
        {
            this.AddLogEntryToContext(DbLoggerSeverity.Critical, category, message, ex);
        }

        /// <summary>
        /// Writes to the log using the error level.
        /// </summary>
        /// <param name="message">The message.</param>
        public void WriteError(string message)
        {
            this.AddLogEntryToContext(DbLoggerSeverity.Error, LogCategories.StreetCare, message, null);
        }

        /// <summary>
        /// Writes to the log using the error level.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The exception</param>
        public void WriteError(string message, Exception ex)
        {
            this.AddLogEntryToContext(DbLoggerSeverity.Error, LogCategories.StreetCare, message, ex);
        }

        /// <summary>
        /// Writes to the log using the error level.
        /// </summary>
        /// <param name="category">The category.</param>
        /// <param name="message">The message.</param>
        /// <param name="ex">The exception</param>
        public void WriteError(BaseCategory category, string message, Exception ex)
        {
            this.AddLogEntryToContext(DbLoggerSeverity.Error, category, message, ex);
        }

        /// <summary>
        /// Writes to the log using the info level.
        /// </summary>
        /// <param name="message">The message.</param>
        public void WriteInfo(string message)
        {
            this.AddLogEntryToContext(DbLoggerSeverity.Information, LogCategories.StreetCare, message, null);
        }

        /// <summary>
        /// Writes to the log using the info level.
        /// </summary>
        /// <param name="category">The category.</param>
        /// <param name="message">The message.</param>
        public void WriteInfo(BaseCategory category, string message)
        {
            this.AddLogEntryToContext(DbLoggerSeverity.Information, category, message, null);
        }

        /// <summary>
        /// Writes to the log using the warning level.
        /// </summary>
        /// <param name="message">The message.</param>
        public void WriteWarning(string message)
        {
            this.AddLogEntryToContext(DbLoggerSeverity.Warning, LogCategories.StreetCare, message, null);
        }

        /// <summary>
        /// Writes to the log using the warning level.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The exception</param>
        public void WriteWarning(string message, Exception ex)
        {
            this.AddLogEntryToContext(DbLoggerSeverity.Warning, LogCategories.StreetCare, message, ex);
        }

        /// <summary>
        /// Writes to the log using the warning level.
        /// </summary>
        /// <param name="category">The category.</param>
        /// <param name="message">The message.</param>
        /// <param name="ex">The exception</param>
        public void WriteWarning(BaseCategory category, string message, Exception ex)
        {
            this.AddLogEntryToContext(DbLoggerSeverity.Warning, category, message, ex);
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Adds a log entry to the Entity Framework context.
        /// </summary>
        /// <param name="severity">The severity.</param>
        /// <param name="category">The category.</param>
        /// <param name="message">The message.</param>
        /// <param name="ex">The exception</param>
        private void AddLogEntryToContext(DbLoggerSeverity severity, BaseCategory category, string message, Exception ex)
        {
            if ((int)severity < (int)this.MinimumSeverity)
            {
                return;
            }

            var logEntry = new LogEntry
            {
                LogEntrySeverity = Enum.Format(typeof(DbLoggerSeverity), severity, "G"),
                LogEntryCategory = category.InternalName,
                LogEntryException = ex != null ? ex.ToString() : string.Empty,
                LogEntryMessage = message,
                LogEntryWhen = DateTime.Now
            };

            var logEntities = new StreetCareLogEntities(IoCHelper.ConfigurationBag.GetConnectionString("StreetCareLogEntities"));
            logEntities.AddToLogEntries(logEntry);
            logEntities.SaveChanges();
        }

        #endregion
    }
}